package com.university.evaluation.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.university.evaluation.common.ResponseResult;
import com.university.evaluation.entity.StudentScoreDetail;
import com.university.evaluation.entity.StudentTotalScore;
import com.university.evaluation.mapper.StudentTotalScoreMapper;
import com.university.evaluation.service.StudentScoreDetailService;
import com.university.evaluation.service.StudentTotalScoreService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StudentTotalScoreServiceImpl extends ServiceImpl<StudentTotalScoreMapper, StudentTotalScore> implements StudentTotalScoreService {

    @Autowired
    private StudentScoreDetailService studentScoreDetailService;

    // --- 查询操作 ---

    @Override
    public ResponseResult<StudentTotalScore> findByStudentIdAndSystemId(String studentId, Long systemId) {
        try {
            StudentTotalScore score = this.getOne(new LambdaQueryWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getStudentId, studentId)
                    .eq(StudentTotalScore::getSystemId, systemId));
            if (score != null) {
                return ResponseResult.success(score);
            }
            return ResponseResult.failure(404, "未找到该学生的总分记录");
        } catch (Exception e) {
            log.error("查询学生总分时发生异常, studentId: {}, systemId: {}", studentId, systemId, e);
            return ResponseResult.failure("查询失败，服务器内部错误");
        }
    }

    @Override
    public ResponseResult<List<StudentTotalScore>> findBySystemId(Long systemId) {
        try {
            List<StudentTotalScore> list = this.list(new LambdaQueryWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getSystemId, systemId));
            return ResponseResult.success(list);
        } catch (Exception e) {
            log.error("按体系ID查询总分列表时发生异常, systemId: {}", systemId, e);
            return ResponseResult.failure("查询失败，服务器内部错误");
        }
    }

    @Override
    public ResponseResult<List<StudentTotalScore>> findByClassIdAndSystemId(Long classId, Long systemId) {
        log.warn("findByClassIdAndSystemId 待实现: 需要在 StudentTotalScoreMapper.xml 中编写JOIN查询");
        return ResponseResult.failure(501, "接口待实现");
    }

    @Override
    public ResponseResult<List<StudentTotalScore>> findByMajorIdAndSystemId(Long majorId, Long systemId) {
        log.warn("findByMajorIdAndSystemId 待实现: 需要在 StudentTotalScoreMapper.xml 中编写JOIN查询");
        return ResponseResult.failure(501, "接口待实现");
    }

    @Override
    public ResponseResult<List<StudentTotalScore>> findByDepartmentIdAndSystemId(Long departmentId, Long systemId) {
        log.warn("findByDepartmentIdAndSystemId 待实现: 需要在 StudentTotalScoreMapper.xml 中编写JOIN查询");
        return ResponseResult.failure(501, "接口待实现");
    }

    // --- 计算与操作 ---

    @Override
    @Transactional
    public ResponseResult<?> calculateAllScoresBySystemId(Long systemId) {
        log.info("开始为测评体系 {} 计算所有学生总分", systemId);
        try {
            List<StudentScoreDetail> allDetails = studentScoreDetailService.list(
                    new LambdaQueryWrapper<StudentScoreDetail>()
                            .eq(StudentScoreDetail::getSystemId, systemId)
                            .eq(StudentScoreDetail::getStatus, 1) // 假设1为已通过
            );

            if (CollectionUtils.isEmpty(allDetails)) {
                return ResponseResult.success("计算完成，该体系下无已审核的成绩明细");
            }

            Map<Long, List<StudentScoreDetail>> detailsByStudent = allDetails.stream()
                    .collect(Collectors.groupingBy(StudentScoreDetail::getStudentId));

            List<StudentTotalScore> totalScoresToSave = new ArrayList<>();

            for (Map.Entry<Long, List<StudentScoreDetail>> entry : detailsByStudent.entrySet()) {
                Long studentId = entry.getKey();
                BigDecimal totalScore = entry.getValue().stream()
                        .map(StudentScoreDetail::getScore)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                StudentTotalScore totalScoreEntity = new StudentTotalScore();
                totalScoreEntity.setStudentId(studentId);
                totalScoreEntity.setSystemId(systemId);
                totalScoreEntity.setTotalScore(totalScore);
                totalScoreEntity.setCalculateTime(LocalDateTime.now());
                totalScoreEntity.setStatus(0);
                totalScoresToSave.add(totalScoreEntity);
            }

            this.remove(new LambdaQueryWrapper<StudentTotalScore>().eq(StudentTotalScore::getSystemId, systemId));
            this.saveBatch(totalScoresToSave);
            log.info("为测评体系 {} 成功计算并保存了 {} 名学生的总分", systemId, totalScoresToSave.size());

            updateRankingBySystemId(systemId);

            return ResponseResult.success("所有学生总分计算完成，并已更新排名");

        } catch (Exception e) {
            log.error("批量计算总分时发生异常, systemId: {}", systemId, e);
            throw new RuntimeException("批量计算总分失败", e);
        }
    }

    @Override
    @Transactional
    public ResponseResult<?> recalculateStudentScore(String studentId, Long systemId) {
        log.info("开始为学生 {} 重新计算体系 {} 的总分", studentId, systemId);
        try {
            List<StudentScoreDetail> scoreDetails = studentScoreDetailService.list(
                    new LambdaQueryWrapper<StudentScoreDetail>()
                            .eq(StudentScoreDetail::getStudentId, studentId)
                            .eq(StudentScoreDetail::getSystemId, systemId)
                            .eq(StudentScoreDetail::getStatus, 1)
            );

            BigDecimal totalScore = scoreDetails.stream()
                    .map(StudentScoreDetail::getScore)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            StudentTotalScore totalScoreEntity = this.getOne(new LambdaQueryWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getStudentId, studentId)
                    .eq(StudentTotalScore::getSystemId, systemId));

            if (totalScoreEntity == null) {
                totalScoreEntity = new StudentTotalScore();
                totalScoreEntity.setStudentId(Long.valueOf(studentId));
                totalScoreEntity.setSystemId(systemId);
            }
            totalScoreEntity.setTotalScore(totalScore);
            totalScoreEntity.setCalculateTime(LocalDateTime.now());

            this.saveOrUpdate(totalScoreEntity);
            return ResponseResult.success("学生总分已成功重新计算");

        } catch (Exception e) {
            log.error("重算单个学生总分时发生异常, studentId: {}", studentId, e);
            throw new RuntimeException("重算单个学生总分失败", e);
        }
    }

    @Override
    @Transactional
    public ResponseResult<?> updateRankingBySystemId(Long systemId) {
        log.info("开始为测评体系 {} 更新排名", systemId);
        try {
            List<StudentTotalScore> allScores = this.list(new LambdaQueryWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getSystemId, systemId)
                    .orderByDesc(StudentTotalScore::getTotalScore));

            if (CollectionUtils.isEmpty(allScores)) {
                return ResponseResult.success("排名更新完成，无记录可排");
            }

            int rank = 1;
            for (int i = 0; i < allScores.size(); i++) {
                StudentTotalScore currentScore = allScores.get(i);
                if (i > 0 && currentScore.getTotalScore().compareTo(allScores.get(i - 1).getTotalScore()) < 0) {
                    rank = i + 1;
                }
                currentScore.setRanking(rank);
            }

            this.updateBatchById(allScores);
            log.info("测评体系 {} 的排名已成功更新", systemId);
            return ResponseResult.success("排名已成功更新");
        } catch (Exception e) {
            log.error("更新排名时发生异常, systemId: {}", systemId, e);
            throw new RuntimeException("更新排名失败", e);
        }
    }

    // --- 发布与状态变更 ---

    @Override
    @Transactional
    public ResponseResult<?> publishScores(Long systemId) {
        try {
            log.info("准备发布测评体系 {} 的成绩", systemId);
            boolean success = this.update(new LambdaUpdateWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getSystemId, systemId)
                    .set(StudentTotalScore::getStatus, 1) // 1-已发布
                    .set(StudentTotalScore::getPublishTime, LocalDateTime.now()));
            return success ? ResponseResult.success("成绩发布成功") : ResponseResult.failure("成绩发布操作失败");
        } catch (Exception e) {
            log.error("发布成绩时发生异常, systemId: {}", systemId, e);
            throw new RuntimeException("发布成绩失败", e);
        }
    }

    @Override
    @Transactional
    public ResponseResult<?> withdrawScores(Long systemId) {
        try {
            log.info("准备撤回测评体系 {} 的成绩", systemId);
            boolean success = this.update(new LambdaUpdateWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getSystemId, systemId)
                    .set(StudentTotalScore::getStatus, 0) // 0-未发布
                    .set(StudentTotalScore::getPublishTime, null));
            return success ? ResponseResult.success("成绩撤回成功") : ResponseResult.failure("成绩撤回操作失败");
        } catch (Exception e) {
            log.error("撤回成绩时发生异常, systemId: {}", systemId, e);
            throw new RuntimeException("撤回成绩失败", e);
        }
    }

    // --- 统计分析 ---

    @Override
    public ResponseResult<Map<String, Object>> getScoreStatistics(Long systemId) {
        try {
            List<StudentTotalScore> scores = this.list(new LambdaQueryWrapper<StudentTotalScore>().eq(StudentTotalScore::getSystemId, systemId));
            if (CollectionUtils.isEmpty(scores)) {
                return ResponseResult.success("获取成功，但该测评体系无成绩数据", Collections.emptyMap());
            }

            Map<String, Object> statistics = new LinkedHashMap<>();

            BigDecimal sum = scores.stream().map(StudentTotalScore::getTotalScore).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal avgScore = sum.divide(new BigDecimal(scores.size()), 2, RoundingMode.HALF_UP);
            statistics.put("averageScore", avgScore);

            Optional<StudentTotalScore> maxScoreOpt = scores.stream().max(Comparator.comparing(StudentTotalScore::getTotalScore));
            Optional<StudentTotalScore> minScoreOpt = scores.stream().min(Comparator.comparing(StudentTotalScore::getTotalScore));
            statistics.put("maxScore", maxScoreOpt.map(StudentTotalScore::getTotalScore).orElse(BigDecimal.ZERO));
            statistics.put("minScore", minScoreOpt.map(StudentTotalScore::getTotalScore).orElse(BigDecimal.ZERO));
            statistics.put("studentCount", scores.size());

            Map<String, Long> scoreDistribution = new LinkedHashMap<>();
            scoreDistribution.put("90-100分", scores.stream().filter(s -> s.getTotalScore().doubleValue() >= 90).count());
            scoreDistribution.put("80-89分", scores.stream().filter(s -> s.getTotalScore().doubleValue() >= 80 && s.getTotalScore().doubleValue() < 90).count());
            scoreDistribution.put("70-79分", scores.stream().filter(s -> s.getTotalScore().doubleValue() >= 70 && s.getTotalScore().doubleValue() < 80).count());
            scoreDistribution.put("60-69分", scores.stream().filter(s -> s.getTotalScore().doubleValue() >= 60 && s.getTotalScore().doubleValue() < 70).count());
            scoreDistribution.put("60分以下", scores.stream().filter(s -> s.getTotalScore().doubleValue() < 60).count());
            statistics.put("scoreDistribution", scoreDistribution);

            return ResponseResult.success("获取成绩统计成功", statistics);
        } catch (Exception e) {
            log.error("获取成绩统计时发生异常, systemId: {}", systemId, e);
            return ResponseResult.failure("获取统计失败，服务器内部错误");
        }
    }

    // --- 新增的缺失方法 ---

    @Override
    public ResponseResult<List<StudentTotalScore>> findByStudentId(String studentId) {
        try {
            List<StudentTotalScore> list = this.list(new LambdaQueryWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getStudentId, Long.valueOf(studentId)));
            return ResponseResult.success(list);
        } catch (Exception e) {
            log.error("按学生ID查询总分列表时发生异常, studentId: {}", studentId, e);
            return ResponseResult.failure("查询失败，服务器内部错误");
        }
    }

    @Override
    public ResponseResult<List<StudentTotalScore>> findByScoreRange(Long systemId, Double minScore, Double maxScore) {
        try {
            List<StudentTotalScore> list = this.list(new LambdaQueryWrapper<StudentTotalScore>()
                    .eq(StudentTotalScore::getSystemId, systemId)
                    .ge(StudentTotalScore::getTotalScore, new BigDecimal(minScore.toString()))
                    .le(StudentTotalScore::getTotalScore, new BigDecimal(maxScore.toString())));
            return ResponseResult.success(list);
        } catch (Exception e) {
            log.error("按分数范围查询总分列表时发生异常, systemId: {}, minScore: {}, maxScore: {}", systemId, minScore, maxScore, e);
            return ResponseResult.failure("查询失败，服务器内部错误");
        }
    }
}